<template>
	<div class="cycle-analysis-container">
		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
			<el-form :model="state.form" ref="queryForm" label-width="90" label-position="right">
				<el-row>
					<el-col :xs="24" :sm="16" :md="12" :lg="10" :xl="8" class="mb10">
						<el-form-item label="关键字">
							<el-input v-model="state.form.keyword" clearable placeholder="请输入模糊查询关键字" />
						</el-form-item>
					</el-col>
					<el-col :xs="24" :sm="8" :md="12" :lg="14" :xl="16" class="mb10" style="display: flex; align-items: center; justify-content: flex-end">
						<el-form-item>
							<el-button-group style="display: flex; align-items: center">
								<el-button type="primary" icon="ele-Search" :loading="state.loading" @click="handleQuery"> 查询 </el-button>
								<el-button :icon="state.showAdvance ? 'ele-ZoomOut' : 'ele-ZoomIn'" @click="toggleAdvance" style="margin-left: 5px"> {{ state.showAdvance ? '隐藏' : '高级查询' }} </el-button>
								<el-dropdown :show-timeout="70" :hide-timeout="50">
									<el-button type="primary" style="margin-left: 5px" icon="ele-FolderOpened"> 导出 </el-button>
									<template #dropdown>
										<el-dropdown-menu>
											<el-dropdown-item @click="exportCurrent">导出本页</el-dropdown-item>
											<el-dropdown-item @click="exportAll">导出全部</el-dropdown-item>
										</el-dropdown-menu>
                    </template>
                  </el-dropdown>
                  <div style="display:flex;align-items:center;margin-left:8px;gap:8px">
                    <el-tag type="success" effect="plain" style="cursor:pointer" @click="scrollToTopQuery">
                      {{ timeRangeText }}
                    </el-tag>
                    <el-tag :type="state.viewMode==='table' ? 'primary' : 'info'" @click="state.viewMode='table'" style="cursor:pointer">表格</el-tag>
                    <el-tag :type="state.viewMode==='summary' ? 'primary' : 'info'" @click="switchToSummary" style="cursor:pointer">统计图</el-tag>
                    <el-tag :type="state.viewMode==='gantt' ? 'primary' : 'info'" @click="switchToGantt" style="cursor:pointer">甘特图</el-tag>
                   
                  </div>
                </el-button-group>
              </el-form-item>
            </el-col>
          </el-row>
				<el-row v-show="state.showAdvance" :gutter="12">
					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
						<el-form-item label="船号">
							<el-input v-model="state.form.ch" clearable placeholder="请输入船号" />
						</el-form-item>
					</el-col>
        <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
          <el-form-item label="分段">
            <el-input v-model="state.form.fd" clearable placeholder="请输入分段" />
          </el-form-item>
        </el-col>
					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
						<el-form-item label="分类">
							<el-select clearable filterable v-model="state.form.className" placeholder="请选择分类">
								<el-option v-for="(item, index) in state.dropdown.className" :key="index" :value="item.value" :label="item.label" />
							</el-select>
						</el-form-item>
					</el-col>
        <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
          <el-form-item label="区域">
            <el-select clearable filterable v-model="state.form.workAreaId" placeholder="请选择区域">
              <el-option v-for="(item, index) in state.dropdown.workAreaId" :key="index" :value="item.value" :label="item.label" />
            </el-select>
          </el-form-item>
        </el-col>

        <!-- 时间范围（本地）：默认跟随顶层，修改后优先使用本地设置 -->
        <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
          <el-form-item label="时间范围" class="time-range-item">
            <el-radio-group v-model="state.form.timeMode" size="small" class="time-mode-group" @change="enableLocalTime">
              <el-radio-button value="month">业务月</el-radio-button>
              <el-radio-button value="custom">自定义</el-radio-button>
              <el-radio-button value="all">全部</el-radio-button>
            </el-radio-group>
            <div class="time-picker-wrap">
              <el-date-picker
                v-if="state.form.timeMode === 'month'"
                class="time-range-picker"
                v-model="state.form.workTime"
                type="month"
                placeholder="选择业务月"
                format="YYYY-MM"
                value-format="YYYY-MM"
                @change="enableLocalTime"
              />
              <el-date-picker
                v-else-if="state.form.timeMode === 'custom'"
                class="time-range-range"
                v-model="state.form.dateRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="YYYY-MM-DD"
                unlink-panels
                @change="enableLocalTime"
              />
              <div v-else></div>
            </div>
          </el-form-item>
        </el-col>

        <!-- 时间范围与维度由上层 QueryForm 统一控制，此处不再重复显示 -->


					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
						<el-form-item label="时间口径">
							<el-radio-group v-model="state.form.timeField" size="small">
								<el-radio-button value="both">计划或实际</el-radio-button>
								<el-radio-button value="plan">仅计划</el-radio-button>
								<el-radio-button value="actual">仅实际</el-radio-button>
							</el-radio-group>
							<el-radio-group v-model="state.form.timeMatch" size="small" style="margin-left: 8px">
								<el-radio-button value="intersects">相交</el-radio-button>
								<el-radio-button value="startWithin">起点</el-radio-button>
								<el-radio-button value="endWithin">终点</el-radio-button>
							</el-radio-group>
						</el-form-item>
					</el-col>

					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
						<el-form-item label="维度">
							<el-select v-model="state.form.dims" multiple collapse-tags collapse-tags-tooltip style="width: 100%" placeholder="选择维度（从上到下决定层级）">
								<el-option v-for="item in dimensionOptions" :key="item.value" :label="item.label" :value="item.value" />
							</el-select>
						</el-form-item>
					</el-col>

					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" class="mb10">
						<el-form-item label="选项">
							<el-checkbox v-model="state.form.onlyCompleted">仅完工</el-checkbox>
							<el-checkbox v-model="state.form.ignoreNegative" style="margin-left: 12px">忽略负周期</el-checkbox>
						</el-form-item>
					</el-col>
				</el-row>
			</el-form>
		</el-card>

		<div v-show="state.viewMode==='table'">
			<el-table
				:key="state.tableKey"
				:data="state.treeData"
				v-loading="state.loading"
				row-key="id"
				border
				style="width: 100%"
				:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
				lazy
				:load="loadChildren"
			>
				<el-table-column label="名称" min-width="240" show-overflow-tooltip>
					<template #default="{ row }">
						{{ getNodeLabel(row) }}
					</template>
				</el-table-column>
				<el-table-column prop="itemCount" label="数量" width="80" align="right" />
				<el-table-column prop="completedCount" label="已完工" width="90" align="right" />
				<el-table-column prop="inProgressCount" label="在制" width="80" align="right" />
				<el-table-column label="计划周期(天)" header-align="center">
					<el-table-column label="合计" width="90" align="right">
						<template #default="{ row }">
							<span>{{ formatSumInt(row.planCycleSumDays) }}</span>
						</template>
					</el-table-column>
					<el-table-column label="平均" width="90" align="right">
						<template #default="{ row }">
							<span>{{ toFixed2Trim(row.planCycleAvgDays) }}</span>
						</template>
					</el-table-column>
				</el-table-column>

				<el-table-column label="实际周期(天)" header-align="center">
					<el-table-column label="合计" width="90" align="right">
						<template #default="{ row }">
							<span>{{ formatSumInt(row.actualCycleSumDays) }}</span>
						</template>
					</el-table-column>
					<el-table-column label="平均" width="90" align="right">
						<template #default="{ row }">
							<span>{{ toFixed2Trim(row.actualCycleAvgDays) }}</span>
						</template>
					</el-table-column>
				</el-table-column>

				<el-table-column label="偏差(天)">
					<el-table-column label="合计" width="90" align="right">
						<template #default="{ row }">
							<span :style="getVarianceStyle(row.varianceSumDays as any)">{{ formatSumInt(row.varianceSumDays) }}</span>
						</template>
					</el-table-column>
					<el-table-column label="平均" width="90" align="right">
						<template #default="{ row }">
							<span :style="getVarianceStyle(row.varianceAvgDays)">{{ toFixed2Trim(row.varianceAvgDays) }}</span>
						</template>
					</el-table-column>
				</el-table-column>
				<el-table-column prop="planSpanDays" label="计划跨度(天)" width="120" align="right" />
				<el-table-column prop="actualSpanDays" label="实际跨度(天)" width="120" align="right" />
			</el-table>

			<div class="table-pagination" style="margin-top: 8px; text-align: right">
				<el-pagination
					background
					layout="total, prev, pager, next, sizes"
					:total="state.total"
					:page-sizes="[10, 20, 50, 100]"
					v-model:current-page="state.pageIndex"
					v-model:page-size="state.pageSize"
					@current-change="handleQuery"
					@size-change="handleQuery"
				/>
			</div>
		</div>

      <div v-show="state.viewMode==='summary'">
        <div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
          <el-button size="small" :disabled="chartDrill.level===0" @click="drillUp">返回</el-button>
          <span style="font-size:12px;color:#909399">{{ breadcrumbText }}</span>
        </div>
        <sc-echarts ref="summaryChartRef" :option="summaryOption" style="height: 520px" />
      </div>

      <!-- 甘特图视图 -->
      <div v-show="state.viewMode==='gantt'">
        <div style="display:flex;align-items:center;gap:8px;margin:8px 0">
          <span style="font-size:12px;color:#909399">甘特引擎</span>
          <el-select v-model="state.ganttEngine" size="small" style="width: 140px">
            <el-option label="标准 (vxe)" value="vxe" />
            <el-option label="dhtmlx (周/月/缩放)" value="dhtmlx" />
          </el-select>
        </div>
        <component
          :is="state.ganttEngine==='dhtmlx' ? DhtmlxGanttContainer : GanttContainer"
          :filters="filtersComputed"
          :dims="state.form.dims"
          :timeField="state.form.timeField"
          :timeMatch="state.form.timeMatch"
        />
      </div>
      
	</div>
</template>

<script lang="ts" setup>
import { reactive, computed, watch, onMounted, ref, nextTick } from 'vue';
import { usePlanViewApi, type CycleTreeRequest, type CycleTreeResponse, type CycleTreeExportRequest, type CycleSummaryRequest, type CycleSummaryResponse, type CycleSummaryRow } from '/@/api/plans/planView';
import { usePlanTypeApi } from '/@/api/plans/planType';
import { getAPI } from '/@/utils/axios-utils';
import { SysOrgApi } from '/@/api-services/api';
import type { SysOrg } from '/@/api-services/models';
import { downloadStreamFile } from '/@/utils/download';
import ScEcharts from '/@/components/scEcharts/index.vue';
import GanttContainer from './GanttContainer.vue';
import DhtmlxGanttContainer from './DhtmlxGanttContainer.vue';

const props = defineProps<{ queryParams?: any }>();
const planViewApi = usePlanViewApi();

const state = reactive({
	dropdown: { className: [] as Array<{ value: number; label: string }>, workAreaId: [] as Array<{ value: number; label: string }> },
	form: {
		keyword: '',
		ch: '',
		fd: '',
		className: undefined as number | undefined,
		workAreaId: undefined as number | undefined,
		timeMode: 'month' as 'month' | 'custom' | 'all',
		workTime: '',
		dateRange: [] as string[],

		timeField: 'both' as 'both' | 'plan' | 'actual',
		timeMatch: 'intersects' as 'intersects' | 'startWithin' | 'endWithin',
		dims: ['ship', 'section', 'category', 'region'] as string[],
		onlyCompleted: true,
		ignoreNegative: true,
	},
	localTimeEnabled: false,
	loading: false,
	treeData: [] as any[],
	total: 0,
	pageIndex: 1,
	pageSize: 50,
	showAdvance: false,
	tableKey: 1,
    viewMode: 'table' as 'table'|'summary'|'gantt',
    ganttEngine: 'dhtmlx' as 'vxe'|'dhtmlx',
    summaryRows: [] as CycleSummaryRow[],
  
});

const dimensionOptions = [
  { value: 'ship', label: '船号' },
  { value: 'section', label: '分段' },
  { value: 'sectionFirst', label: '分段首位' },
  { value: 'category', label: '分类' },
  { value: 'region', label: '区域' },
];

// ========= 图表层级钻取状态 =========
const chartDrill = reactive({
  level: 0, // 当前展示的层级（0 表示 dims[0]）
  parentPath: [] as string[], // 当前父路径（长度 = level）
});
// 友好面包屑：parentPath 存原始键（如ID），此处映射成显示名
const breadcrumbText = computed(()=>{
  if (chartDrill.level === 0) return '根层';
  const parts: string[] = [];
  for (let i = 0; i < chartDrill.level; i++) {
    const key = chartDrill.parentPath[i];
    let friendly = '';
    const dim = state.form.dims[i] || '';
    if (i === 0) {
      // 从根表格数据匹配第0层
      const n = (state.treeData as any[] || []).find((x:any) => (x.keyPath || [])[0] === key);
      friendly = (n?.labels?.[dim]) ?? (n?.keyPath?.[0]) ?? key;
    } else {
      // 从当前summaryRows中匹配路径前缀+本层key，取displayKeyPath[i]
      const row = (state.summaryRows as any[] || []).find((r:any) => {
        const kp = r.keyPath || [];
        if (kp.length <= i) return false;
        for (let j=0;j<i;j++) if (kp[j] !== chartDrill.parentPath[j]) return false;
        return kp[i] === key;
      });
      friendly = (row?.displayKeyPath?.[i]) ?? (row?.keyPath?.[i]) ?? key;
    }
    parts.push(String(friendly || key));
  }
  return `层级 ${chartDrill.level}: ` + parts.join(' / ');
});
 

const filtersComputed = computed(() => {
  const q = props.queryParams || {};
  const f: any = {
    className: q.className ?? state.form.className,
    workAreaId: q.workAreaId ?? state.form.workAreaId,
    keyword: state.form.keyword,
    shipNos: state.form.ch ? [state.form.ch] : undefined,
    sections: state.form.fd ? [state.form.fd] : undefined,
    onlyCompleted: state.form.onlyCompleted,
    ignoreNegative: state.form.ignoreNegative,
  };
  if (state.localTimeEnabled) {
    if (state.form.timeMode === 'month' && state.form.workTime) {
      f.workTime = state.form.workTime;
    } else if (state.form.timeMode === 'custom' && state.form.dateRange && state.form.dateRange.length === 2) {
      f.rangeStart = state.form.dateRange[0] + ' 00:00:00';
      f.rangeEnd = state.form.dateRange[1] + ' 23:59:59';
    } else if (state.form.timeMode === 'all') {
      f.rangeStart = '1900-01-01 00:00:00';
      f.rangeEnd = '2099-12-31 23:59:59';
    }
  } else {
    if (q.rangeStart && q.rangeEnd) {
      f.rangeStart = q.rangeStart;
      f.rangeEnd = q.rangeEnd;
    } else if (q.workTime) {
      f.workTime = q.workTime;
    }
  }
  return f;
});

function enableLocalTime() {
  state.localTimeEnabled = true;
}

// 同步顶层的时间范围到本地控件（未启用本地覆盖时）
watch(() => props.queryParams, (q: any) => {
  if (!q) return;
  if (state.localTimeEnabled) return;
  if (q.rangeStart && q.rangeEnd) {
    state.form.timeMode = 'custom';
    const s = String(q.rangeStart).slice(0,10);
    const e = String(q.rangeEnd).slice(0,10);
    state.form.dateRange = [s, e];
  } else if (q.workTime) {
    state.form.timeMode = 'month';
    state.form.workTime = q.workTime;
  } else {
    state.form.timeMode = 'all';
  }
}, { immediate: true, deep: true });

// 只读时间范围标签文本：优先显示自定义范围，否则业务月，否则“全部”
const timeRangeText = computed(() => {
  const f: any = filtersComputed.value || {};
  if (f.rangeStart && f.rangeEnd) {
    const s = String(f.rangeStart).slice(0, 10);
    const e = String(f.rangeEnd).slice(0, 10);
    return `时间：${s} ~ ${e}`;
  }
  if (f.workTime) return `业务月：${f.workTime}`;
  return '时间：全部';
});

function scrollToTopQuery() {
  const el = document.querySelector('.query-form-card');
  if (el && 'scrollIntoView' in el) (el as any).scrollIntoView({ behavior: 'smooth', block: 'start' });
}

function getNodeLabel(row: any) {
	// 优先按层级给出对应维度的标签
	const level = row.level;
	const dim = state.form.dims[level] || 'ship';
	const name = row.labels?.[dim] ?? row.keyPath?.[level] ?? '';
	return name;
}

function getVarianceStyle(v: number | undefined | null) {
	if (v == null) return {};
	if (v > 0.01) return { color: '#d03050' };
	if (v < -0.01) return { color: '#2db47c' };
	return {};
}

function toFixed2Trim(n: number | undefined | null): string {
	if (n == null || isNaN(n as any)) return '';
	return Number(n)
		.toFixed(2)
		.replace(/\.00$/, '')
		.replace(/(\.\d*[1-9])0$/, '$1');
}

function formatSumInt(n: number | undefined | null): string {
	if (n == null || isNaN(n as any)) return '';
	return String(Math.round(Number(n)));
}

// 展示为 "合计 | 平均"；合计不带小数，平均四舍五入到2位并去掉末尾0
function formatPair(sum: number | undefined | null, avg: number | undefined | null): string {
	const left = formatSumInt(sum);
	const right = toFixed2Trim(avg);
	if (left && right) return `${left} | ${right}`;
	return left || right || '';
}

// 偏差也展示为 合计|平均
function formatPairVariance(sum: number | undefined | null, avg: number | undefined | null): string {
	return formatPair(sum, avg);
}

async function loadTree() {
	state.loading = true;
	try {
		const req: CycleTreeRequest = {
			filters: filtersComputed.value,
			dims: state.form.dims.slice(),
			timeField: state.form.timeField,
			timeMatch: state.form.timeMatch,
			pageIndex: state.pageIndex,
			pageSize: state.pageSize,
			sort: [{ field: 'ActualCycleAvgDays', desc: true }],
			lazy: true,
		} as any;
		const res = await planViewApi.getCycleTree(req);
		const data = (res.data?.result || res.data) as CycleTreeResponse;
		state.treeData = data.nodes || [];
		state.total = data.total || 0;
	} finally {
		state.loading = false;
	}
}

async function handleQuery() {
	await loadTree();
	state.tableKey++;
  if (state.viewMode==='summary') await loadSummary();
  
}

async function loadChildren(row: any, treeNode: any, resolve: (data: any[]) => void) {
	try {
		const req: CycleTreeRequest = {
			filters: filtersComputed.value,
			dims: state.form.dims.slice(),
			timeField: state.form.timeField,
			timeMatch: state.form.timeMatch,
			lazy: true,
			parentKeyPath: row.keyPath,
		} as any;
		const res = await planViewApi.getCycleTree(req);
		const data = (res.data?.result || res.data) as CycleTreeResponse;
		resolve(data.nodes || []);
	} catch (e) {
		resolve([]);
	}
}

// 默认业务月的计算已迁移到上层 QueryForm

function toggleAdvance() {
	state.showAdvance = !state.showAdvance;
}

async function exportCurrent() {
	const req: CycleTreeExportRequest = {
		filters: filtersComputed.value,
		dims: state.form.dims.slice(),
		timeField: state.form.timeField,
		timeMatch: state.form.timeMatch,
		pageIndex: state.pageIndex,
		pageSize: state.pageSize,
		sort: [{ field: 'ActualCycleAvgDays', desc: true }],
		lazy: true,
		exportAll: false,
	} as any;
	const res = await planViewApi.exportCycleTree(req);
	downloadStreamFile(res);
}

async function exportAll() {
	const req: CycleTreeExportRequest = {
		filters: filtersComputed.value,
		dims: state.form.dims.slice(),
		timeField: state.form.timeField,
		timeMatch: state.form.timeMatch,
		sort: [{ field: 'ActualCycleAvgDays', desc: true }],
		lazy: true,
		exportAll: true,
		exportAllLevels: true,
	} as any;
	const res = await planViewApi.exportCycleTree(req);
	downloadStreamFile(res);
}

onMounted(async () => {
	// 下拉：分类
	const planTypeApi = usePlanTypeApi();
  const planTypeData = await planTypeApi.page({ page: 1, pageSize: 99999999 }).then((res: any) => res.data.result);
  state.dropdown.className = (planTypeData?.items ?? [])
    .sort((a:any,b:any)=> (a.orderNo ?? 0) - (b.orderNo ?? 0))
    .map((x: any) => ({ value: x.id, label: x.name }));
	// 下拉：区域
	const orgData = await getAPI(SysOrgApi)
		.apiSysOrgListGet(0)
		.then((res: any) => res.data.result);
  const extractAllOrgs = (orgs: SysOrg[]): Array<{ value: number; label: string; orderNo?: number }> => {
    const result: Array<{ value: number; label: string; orderNo?: number }> = [];
    orgs.forEach((org) => {
      if (org.children && org.children.length > 0) result.push(...extractAllOrgs(org.children as any));
      else result.push({ value: Number(org.id), label: String(org.name), orderNo: (org as any).orderNo });
    });
    return result;
  };
  state.dropdown.workAreaId = extractAllOrgs(orgData || [])
    .sort((a,b)=> (a.orderNo ?? 0) - (b.orderNo ?? 0))
    .map(x=> ({ value: x.value, label: x.label }));
	await handleQuery();
});

// ========== 统计图 ==========
const summaryOption = computed(() => {
  // 将后端返回的叶子级 rows，根据 drill 状态聚合到下一层展示
  const parentLen = chartDrill.parentPath.length;
  const nextLevel = Math.min(parentLen + 1, state.form.dims.length);
  const groups = new Map<string, { plan: number; actual: number }>();
  for (const r of state.summaryRows) {
    const kp = r.keyPath || [];
    // 只取在当前父路径下的行
    let ok = kp.length >= nextLevel;
    if (ok) {
      for (let i=0;i<parentLen;i++) if (kp[i] !== chartDrill.parentPath[i]) { ok=false; break; }
    }
    if (!ok) continue;
    const key = kp[nextLevel-1] || (r.label || r.id);
    const acc = groups.get(key) || { plan: 0, actual: 0 };
    acc.plan += r.planCycleSumDays ?? 0;
    acc.actual += r.actualCycleSumDays ?? 0;
    groups.set(key, acc);
  }
  const keys = Array.from(groups.keys());
  // 展示名称优先使用 displayKeyPath 对应层的友好名
  const x = keys.map((k,i)=> {
    const match = state.summaryRows.find(r=> (r.keyPath||[])[nextLevel-1]===k);
    const friendly = match?.displayKeyPath?.[nextLevel-1] || k;
    return `${i+1}. ${friendly}`;
  });
  const plan = keys.map(k=> groups.get(k)!.plan);
  const actual = keys.map(k=> groups.get(k)!.actual);
  return {
    tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
    legend: { data: ['计划周期(合计)','实际周期(合计)'] },
    grid: { left: 60, right: 20, top: 40, bottom: 80 },
    xAxis: {
      type: 'category',
      data: x,
      axisLabel: {
        interval: 0,
        rotate: 28,
        formatter: (v: string) => (v && v.length > 18 ? v.slice(0, 18) + '…' : v)
      }
    },
    yAxis: { type: 'value', name: '天(合计)' },
    dataZoom: x.length > 10 ? [{ type: 'slider', xAxisIndex: 0, bottom: 30 }, { type: 'inside', xAxisIndex: 0 }] : [],
    series: [
      {
        name: '计划周期(合计)',
        type: 'bar',
        data: plan,
        itemStyle: { color: '#91cc75' },
        barCategoryGap: '40%',
        label: { show: true, position: 'top', color: '#606266', fontSize: 12, formatter: ({ value }: any) => (value ?? 0) }
      },
      {
        name: '实际周期(合计)',
        type: 'bar',
        data: actual,
        itemStyle: { color: '#5470c6' },
        barCategoryGap: '40%',
        label: { show: true, position: 'top', color: '#606266', fontSize: 12, formatter: ({ value }: any) => (value ?? 0) }
      },
    ],
  } as any;
});

async function loadSummary() {
  if (chartDrill.level === 0) {
    // 根层：直接从表格当前根节点构建，确保与表格分页/过滤一致
    const roots = (state.treeData || []) as any[];
    state.summaryRows = roots.map((n:any) => {
      const kp = (n.keyPath || []) as string[];
      const labels = (n.labels || {}) as Record<string,string>;
      const displayPath = state.form.dims.map((d:string)=> labels[d] ?? '');
      return {
        id: n.id,
        keyPath: kp,
        label: kp[kp.length-1] || n.id,
        displayKeyPath: displayPath,
        displayLabel: displayPath[displayPath.length-1] || (kp[kp.length-1] || n.id),
        planCycleSumDays: n.planCycleSumDays ?? 0,
        actualCycleSumDays: n.actualCycleSumDays ?? 0,
      } as any;
    });
  } else {
    const req: CycleSummaryRequest = {
      filters: filtersComputed.value,
      dims: state.form.dims.slice(),
      timeField: state.form.timeField,
      timeMatch: state.form.timeMatch,
      pageIndex: 1,
      pageSize: 1000,
      targetKeyPath: chartDrill.parentPath.slice(),
    } as any;
    const res = await planViewApi.getCycleSummary(req);
    const data = (res.data?.result || res.data) as CycleSummaryResponse;
    state.summaryRows = data.rows || [];
  }
  // 绑定统计图点击下钻
  await nextTick();
  bindSummaryClick();
  // 切换/加载后强制 resize，避免显示异常
  await nextTick();
  summaryChartRef.value?.resize?.();
}

function switchToSummary() {
  state.viewMode = 'summary';
  // 重置到根层
  chartDrill.level = 0; chartDrill.parentPath = [];
  loadSummary();
}

 

// 点击统计图行进行下钻
const summaryChartRef = ref<any>(null);
let onSummaryClick: any = null;
function bindSummaryClick() {
  const inst = summaryChartRef.value?.getInstance?.();
  if (!inst) return;
  if (onSummaryClick) inst.off('click', onSummaryClick);
  onSummaryClick = (p: any) => {
    if (!p || (p.seriesType !== 'bar')) return;
    const cat = p?.name as string; // like '01. Label'
    const label = (cat || '').replace(/^\d+\.\s*/, '');
    const parentLen = chartDrill.parentPath.length;
    const nextLevel = Math.min(parentLen + 1, state.form.dims.length);
    // 在当前父路径下，找到 label 对应的 key（第 nextLevel 维的键）
    // 若未到叶子，则钻取到下一层；若已到叶子，停留在当前层（后续如需详情再扩展）
    // 直接用后端rows，根据 prefix 过滤
    const candidates = state.summaryRows.filter(r => {
      const kp = r.keyPath || [];
      const dp = r.displayKeyPath || [];
      if (kp.length < nextLevel) return false;
      for (let i=0;i<parentLen;i++) if (kp[i] !== chartDrill.parentPath[i]) return false;
      return (dp[nextLevel-1] === label) || (kp[nextLevel-1] === label);
    });
    if (nextLevel < state.form.dims.length) {
      // 下钻
      chartDrill.level = nextLevel;
      // 使用原始key进行下钻，避免将显示名传给后端导致无数据
      const selectedKey = candidates[0]?.keyPath?.[nextLevel-1] ?? label;
      chartDrill.parentPath = [...chartDrill.parentPath, selectedKey];
      loadSummary();
    } else if (candidates.length > 0) {
      // 到达叶子：不再继续下钻，保留到此层（后续按你指导再做详情）
    }
  };
  inst.on('click', onSummaryClick);
}

function drillUp() {
  if (chartDrill.level === 0) return;
  chartDrill.parentPath = chartDrill.parentPath.slice(0, chartDrill.parentPath.length - 1);
  chartDrill.level -= 1;
  loadSummary();
}

// 当视图切换为 summary 时，确保 resize 一次避免初次不可见导致尺寸为0
watch(() => state.viewMode, async (v) => {
  if (v === 'summary') {
    await nextTick();
    summaryChartRef.value?.resize?.();
  }
});

function switchToGantt() {
  state.viewMode = 'gantt';
  // 触发一次全局resize，确保ECharts在由隐藏->可见时能正确计算尺寸
  nextTick(() => window.dispatchEvent(new Event('resize')));
}


// 甘特图功能已移除
</script>

<style scoped>
.time-range-item :deep(.el-form-item__content) {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
}
.time-mode-group { flex: 0 0 auto; flex-shrink: 0; }
.time-picker-wrap {
  flex: 1 1 0%;
  min-width: 0;
  display: flex;
}
.time-range-picker,
.time-range-range { width: 100%; }
.time-picker-wrap :deep(.el-date-editor) { width: 100%; }
.time-picker-wrap :deep(.el-date-editor--daterange) { width: 100%; }
.time-picker-wrap :deep(.el-range-editor) { width: 100%; }
.time-picker-wrap :deep(.el-range-editor .el-range-input) { min-width: 0; }
.time-picker-wrap :deep(.el-range-editor .el-range-separator) { flex: 0 0 auto; }
</style>
